pacman::p_load(tidyverse,
               haven,
               broom,
               cowplot,
               rgdal,
               rgeos,
               maps,
               maptools,
               grid,
               gridExtra)

# load geoinformation on Ukraine
ukraine <- map_data(map = "world", region = "ukraine")

# function to transform codes for Ukrainian regions
recode_reg <- function(reg_code) {
  rec_code <- as.character(reg_code)
  reg_code <- substr(reg_code, 3, length(reg_code))
  return(reg_code)
}

# load data on political alignment of oligarch groups
group_alignment <- read_csv("Additional Data/groups_alignment.csv") %>% 
  rename(oligarch_group = group)

# load data on regions of oligarch-controlled firms from Delo/UP
delo_up <- read_dta("Additional Data/Delo_UP_IV_sample_regions.dta") %>%
  select(-c(macroeast, macrowest, macrocenter, macrosouth))

# load data on oligarch groups of firms from Delo/UP
delo_up_groups <- read_dta("Delo_UP.dta") %>%
  select(okpo, group)

# join the data sets
delo_up <- left_join(delo_up, delo_up_groups)
delo_up <- left_join(delo_up,
                     group_alignment %>%
                       rename(group = oligarch_group,
                              alignment_po = alignment))

# load data on Ukrainian regions
ukraine_data <- read_dta("Additional Data/Ukraine_regions.dta")
ukraine_data$reg_code <- recode_reg(ukraine_data$region)
reg_codes <- ukraine_data %>% dplyr::select(reg_code, regname)

# add regional codes to the data set of firms
delo_up <- left_join(delo_up, reg_codes)

# data on percent voted for Yushchenko in Ukrainian regions
regional_vote <- ukraine_data %>% dplyr::select(reg_code, YuDec)
regional_vote <- regional_vote %>%
  rename(Yushchenko = YuDec) %>%
  mutate(Yanukovych = 1 - Yushchenko)
regional_vote <- gather(regional_vote, Candidate, Vote,-reg_code)

# load geoinformation on Ukraine administrative divisions (regions)
# https://data.humdata.org/dataset/ukraine-administrative-boundaries-as-of-q2-2017
# a set of files with names starting from "ukr_admbnda_adm1_q2_sspe_20171221"
# has to be in the script directory
ukraine_map <-
  readOGR(dsn = ".", layer = "ukr_admbnda_adm1_q2_sspe_20171221")
ukraine_map@data$reg_code <- recode_reg(ukraine_map@data$ADM1_PCODE)

# join with data on regions
ukraine_map@data <-
  left_join(ukraine_map@data, ukraine_data, by = "reg_code")
ukraine_map@data$id <- rownames(ukraine_map@data)

# build the map
ukraine_map.points <- fortify(ukraine_map, region = "id")
ukraine_map.df <-
  left_join(ukraine_map.points, ukraine_map@data, by = "id")
region_centroids <- gCentroid(ukraine_map, byid = TRUE)
region_centroids <- as.data.frame(region_centroids)
colnames(region_centroids) <- paste(c("long", "lat"))
region_centroids$reg_code <- ukraine_map@data$reg_code

ukr_df <- broom::tidy(ukraine_map, region = "regname")
rnames <- aggregate(cbind(long, lat) ~ id, data = ukr_df, FUN = mean)
ukr_df <- broom::tidy(ukraine_map, region = "reg_code")
ukr_data <- ukraine_data %>% rename(id = reg_code)
ukr_df <- left_join(ukr_df, ukr_data)

# number of firms by region
firms_by_region <- delo_up %>%
  dplyr::select(reg_code, regname, okpo) %>%
  group_by(reg_code) %>%
  summarise(firms = n())

# randomly disperse firm locations within each region
points_by_region <- function(region) {
  print(region)
  region_map <- ukraine_map[ukraine_map@data$reg_code == region, ]
  firm_count_by_region <-
    firms_by_region[firms_by_region$reg_code == region, ]$firms
  firm_codes <- delo_up[delo_up$reg_code == region, ]$okpo
  points <- spsample(region_map, firm_count_by_region, "random")
  #  points <- sample_n(region_map, firm_count_by_region, replace = FALSE)
  points <- as.data.frame(points)
  points <- points %>%
    rename(long = x, lat = y) %>%
    mutate(reg_code = region)
  points$okpo <- firm_codes
  points <- left_join(points,
                      delo_up %>% select(okpo, group, alignment_po))
  return(points)
}

# here the code works somewhat unpredictably because of randomness,
# so in case of error, the next line needs to be run again
# (it will ultimately work out)
firm_random_locations <-
  purrr::map_df(unique(firms_by_region$reg_code),
             points_by_region)
firm_random_locations$alignment_po <-
  factor(firm_random_locations$alignment_po,
         levels = c("Blue", "Orange", "Gray"))

# Kyiv inset
Kyivxlim <-
  range(ukr_df[ukr_df$id == "80", ]$long) + c(-0.125, 0.125)
Kyivylim <- range(ukr_df[ukr_df$id == "80", ]$lat) + c(-0.125, 0.125)

# regions by color with firms as black dots
plot_regions_by_color <- function(oligarch_group) {
  if (oligarch_group == "all") {
    firm_locations <- firm_random_locations
    plot_title <- ""
  } else {
    firm_locations <-
      firm_random_locations[firm_random_locations$oligarch_group == oligarch_group, ]
    plot_title <- oligarch_group
  }
  
  # plot of all the regions
  reg_plot <- ggplot() +
    geom_polygon(data = ukr_df, aes(
      x = long,
      y = lat,
      fill = YuDec,
      group = group
    )) +
    scale_fill_gradient(low = "blue", high = "orange") +
    geom_path(
      data = ukr_df,
      aes(x = long, y = lat, group = group),
      color = "black",
      size = 0.3
    ) +
    coord_fixed(1.3) +
    geom_text(data = rnames,
              aes(x = long, y = lat, label = id),
              size = 2) +
    geom_point(data = firm_locations %>% filter(reg_code != "80"),
               aes(x = long, y = lat),
               size = 1) +
    theme_void() +
    theme(legend.position = c(0.93, 0.88)) +
    guides(fill = guide_colourbar(title = "Yushchenko\nvote")) +
    ggtitle(plot_title) +
    theme(plot.title = element_text(hjust = 0.5))
  
  # Kyiv inset
  Kyiv_plot <- ggplot() +
    geom_polygon(data = ukr_df %>% filter(id == "80"),
                 aes(
                   x = long,
                   y = lat,
                   fill = YuDec,
                   group = group
                 )) +
    scale_fill_gradient(low = "blue",
                        high = "orange",
                        guide = "none") +
    geom_path(
      data = ukr_df %>% filter(id == "80"),
      aes(x = long, y = lat, group = group),
      color = "black",
      size = 0.3
    ) +
    coord_fixed(1.3) +
    geom_point(data = firm_locations %>% filter(reg_code == "80"),
               aes(x = long, y = lat),
               size = 1) +
    annotate(
      "text",
      x = 30.3,
      y = 50.3,
      label = "Kyiv",
      size = 4
    ) +
    geom_rect(
      data = data.frame(),
      aes(
        xmin = Kyivxlim[1],
        xmax = Kyivxlim[2],
        ymin = Kyivylim[1],
        ymax = Kyivylim[2]
      ),
      colour = "black",
      fill = NA
    ) +
    theme_void()
  
  # combined plot
  plot_combined <- reg_plot +
    annotation_custom(
      grob = ggplotGrob(Kyiv_plot),
      xmin = min(ukr_df$long) - 10,
      xmax = min(ukr_df$long) + 15.8,
      ymin = max(ukr_df$lat) - 8.5,
      ymax = max(ukr_df$lat) - 4.9
    )
  
  return(plot_combined)
}

# plot of firms by color on the white background
firms_color_plot <- ggplot() +
  geom_polygon(data = ukr_df,
               aes(x = long, y = lat, group = group),
               fill = "white") +
  geom_path(
    data = ukr_df,
    aes(x = long, y = lat, group = group),
    color = "black",
    size = 0.3
  ) +
  coord_fixed(1.3) +
  geom_text(data = rnames, aes(x = long, y = lat, label = id), size = 2) +
  geom_point(
    data = firm_random_locations %>% filter(reg_code != "80"),
    aes(
      x = long,
      y = lat,
      color = alignment_po,
      shape = alignment_po
    ),
    size = 1
  ) +
  scale_color_manual(values = c("blue", "orange", "gray")) +
  scale_shape_manual(values = 15:17) +
  theme_void() +
  theme(legend.position = c(0.93, 0.88)) +
  guides(
    color = guide_legend(title = "Political\nconnections"),
    shape = guide_legend(title = "Political\nconnections")
  )

# Kyiv inset
firms_Kyiv <- ggplot() +
  geom_polygon(
    data = ukr_df %>% filter(id == "80"),
    aes(x = long, y = lat, group = group),
    fill = "white"
  ) +
  geom_path(
    data = ukr_df %>% filter(id == "80"),
    aes(x = long, y = lat, group = group),
    color = "black",
    size = 0.3
  ) +
  coord_fixed(1.3) +
  #  geom_text(data = rnames %>% filter(id == "Kyiv"),
  #  aes(x = long, y = lat, label = id), size = 2) +
  geom_point(
    data = firm_random_locations %>% filter(reg_code == "80"),
    aes(x = long, y = lat, color = alignment_po),
    size = 1
  ) +
  scale_color_manual(values = c("blue", "orange", "gray"),
                     guide = "none") +
  scale_shape_manual(values = 15:17, guide = "none") +
  annotate(
    "text",
    x = 30.3,
    y = 50.3,
    label = "Kyiv",
    size = 4
  ) +
  geom_rect(
    data = data.frame(),
    aes(
      xmin = Kyivxlim[1],
      xmax = Kyivxlim[2],
      ymin = Kyivylim[1],
      ymax = Kyivylim[2]
    ),
    colour = "black",
    fill = NA
  ) +
  theme_void()

# combined plot
firms_color_plot_combined <- firms_color_plot +
  annotation_custom(
    grob = ggplotGrob(firms_Kyiv),
    xmin = min(ukr_df$long) - 10,
    xmax = min(ukr_df$long) + 15.8,
    ymin = max(ukr_df$lat) - 8.5,
    ymax = max(ukr_df$lat) - 4.9
  )

# firms by region on white background + voting results by region
reg_codes <- reg_codes[order(reg_codes$reg_code), ]

vote_plot_list <-
  purrr::map(reg_codes$reg_code, function(i) {
    gt_plot <- ggplotGrob(
      ggplot(data = regional_vote[regional_vote$reg_code == i, ],
             aes(Candidate, Vote, fill = Candidate)) +
        geom_bar(position = 'dodge', stat = 'identity') +
        scale_fill_manual(
          "legend",
          values = c("Yanukovych" = "blue",
                     "Yushchenko" = "orange")
        ) +
        labs(x = NULL, y = NULL) +
        theme(
          legend.position = "none",
          rect = element_blank(),
          line = element_blank(),
          text = element_blank()
        )
    )
    panel_coords <- gt_plot$layout[gt_plot$layout$name == "panel", ]
    gt_plot[panel_coords$t:panel_coords$b, panel_coords$l:panel_coords$r]
  })

vote_annotation_list <-
  purrr::map(1:length(reg_codes$reg_code), function(i)
    annotation_custom(
      vote_plot_list[[i]],
      xmin = region_centroids$long[region_centroids$reg_code == reg_codes$reg_code[i]] - 0.3,
      xmax = region_centroids$long[region_centroids$reg_code == reg_codes$reg_code[i]] + 0.3,
      ymin = region_centroids$lat[region_centroids$reg_code == reg_codes$reg_code[i]] - 0.3,
      ymax = region_centroids$lat[region_centroids$reg_code == reg_codes$reg_code[i]] + 0.3
    ))

result_plot <-
  Reduce(`+`, vote_annotation_list, firms_color_plot_combined)

# plot of firms with regions colored by Yushchenko vote (Figure 2)
plot_regions_by_color("all")
ggsave("Results/Figure_2.png",
       width = 8,
       height = 5,
       units = "in")

# plot of firms colored by political connections (Figure 3)
print(firms_color_plot_combined)
ggsave(
  "Results/Figure_3.png",
  width = 8,
  height = 5,
  units = "in"
)
